package com.slink.fxfk.common.dao.imp;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.internal.CriteriaImpl;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class BaseDao<T> extends HibernateDaoSupport {
	
	public void delete(T o) {
		this.getHibernateTemplate().delete(o);
	}

	public void insert(T o) {
		this.getHibernateTemplate().save(o);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public T select(Class cls, Serializable id) {
		return (T) this.getHibernateTemplate().get(cls, id);
	}

	public void update(T o) {
		this.getHibernateTemplate().update(o);
	}

	@SuppressWarnings("unchecked")
	public List<T> getAll(String className) {
		String queryString = "from " + className;
		return (List<T>) this.getHibernateTemplate().find(queryString);
	}

	@SuppressWarnings("unchecked")
	public List<T> getAllByQuery(String queryString) {
		return (List<T>) this.getHibernateTemplate().find(queryString);
	}

	public Query getQuery(final String queryStr) throws DataAccessException {
		@SuppressWarnings({ "unchecked", "rawtypes" })
		Query query = (Query) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session) {
						return session.createQuery(queryStr);
					}
				});
		return query;
	}

	@SuppressWarnings("unchecked")
	public List<T> getListByQuery(final String queryString, final int pageSize,
			final int pageIndex) {
		// Query query =
		// this.getHibernateTemplate().getSessionFactory().getCurrentSession().createQuery(queryString);
		Query query = getQuery(queryString);
		query.setFirstResult(pageIndex * pageSize);
		query.setMaxResults(pageSize);
		return query.list();
	}

	@SuppressWarnings("unchecked")
	public List<T> findByProperty(String className, String propertyName,
			Object value) throws Exception {
		String queryString = "from " + className + " where " + propertyName
				+ " =?";
		return (List<T>) this.getHibernateTemplate().find(queryString, value);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public int findByCriteriaCount(final DetachedCriteria detachedCriteria) {
		return (Integer) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException {
						Criteria criteria = detachedCriteria
								.getExecutableCriteria(session);
						return ((Integer) criteria.setProjection(
								Projections.rowCount()).uniqueResult())
								.intValue();
					}
				});
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public Map<String, Object> findPageByCriteria(
			final DetachedCriteria detachedCriteria, final int pageSize,
			final int pageIndex) throws Exception {
		return (Map<String, Object>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException {
						Criteria criteria = detachedCriteria
								.getExecutableCriteria(session);
						List items = criteria.setFirstResult(pageIndex)
								.setMaxResults(pageSize).list();
						int totalCount = items.size();
						if (totalCount >= pageSize) {
							// 移除order chanHo 20080415
							@SuppressWarnings("unused")
							List orderEntrys = null;
							Field field = null;

							CriteriaImpl impl = (CriteriaImpl) criteria;
							try {
								field = CriteriaImpl.class
										.getDeclaredField("orderEntries");
								field.setAccessible(true);// 这是关键：）
								orderEntrys = (List) field.get(impl);
								field.set(criteria, new ArrayList());
							} catch (Exception e) {
								e.printStackTrace();
							}

							criteria.setProjection(null);
							criteria.setFirstResult(0).setMaxResults(1);
							totalCount = ((Integer) criteria.setProjection(
									Projections.rowCount()).uniqueResult())
									.intValue();
							criteria.setProjection(null);
							criteria.setProjection(null);
							criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
							// 恢復order , 不過不建議重用detachedCriteria
							// ,目前Criteria有很多問題!後面的代碼可以注釋掉
							/*
							 * List innerOrderEntries = null; try {
							 * innerOrderEntries = (List)field.get(criteria); }
							 * catch (Exception e) { e.printStackTrace(); }
							 * for(int i=0;i<orderEntrys.size();i++){
							 * innerOrderEntries.add(orderEntrys.get(i)); }
							 */
						}
						Map reyurnMap = new HashMap<String, Object>();
						reyurnMap.put("count", totalCount);
						reyurnMap.put("page", items);
						return reyurnMap;
					}
				});
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public List<T> findPageByCriteriaOrderBy(
			final DetachedCriteria detachedCriteria, final int pageSize,
			final int pageIndex) throws Exception {
		return (List<T>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException {
						Criteria criteria = detachedCriteria
								.getExecutableCriteria(session);
						List items = criteria
								.setFirstResult(pageIndex * pageSize)
								.setMaxResults(pageSize).list();
						return items;
					}
				});
	}

	@SuppressWarnings("unchecked")
	public List<T> findByCriteria(DetachedCriteria detachedCriteria)
			throws Exception {
		return (List<T>) this.getHibernateTemplate().findByCriteria(
				detachedCriteria);
	}

	/**
	 * 
	 * @param queryStr
	 * @param pageSize
	 * @param pageIndex
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public Map<String, Object> findPageByQuery(final String queryStr,
			final int pageSize, final int pageIndex) throws Exception {
		return (Map<String, Object>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException {
						Query query = session.createQuery(queryStr);
						List items = query.setFirstResult(pageIndex * pageSize)
								.setMaxResults(pageSize).list();
						long totalCount = items.size();
						if (totalCount == pageSize || totalCount == 0) {
							int fromIndex = queryStr.toLowerCase().indexOf(
									"from");
							int orderIndex = queryStr.toLowerCase().indexOf(
									"order");
							String countQueryStr = "";
							if (orderIndex != -1) {
								countQueryStr = "select count(*) "
										+ queryStr.substring(fromIndex,
												orderIndex);
							} else {
								countQueryStr = "select count(*) "
										+ queryStr.substring(fromIndex);
							}
							Query CountQuery = session
									.createQuery(countQueryStr);
							totalCount = (Long) CountQuery.uniqueResult();
							System.out.println("totalCount=" + totalCount);
						} else if (totalCount > 0 && totalCount < pageSize) {
							totalCount = pageSize * pageIndex + totalCount;
						}

						Map reyurnMap = new HashMap<String, Object>();
						reyurnMap.put("count", totalCount);
						reyurnMap.put("page", items);
						return reyurnMap;
					}
				});
	}
	
	

}
